package com.phenix.mvp.aop.aspect;

import com.orhanobut.logger.Logger;
import com.phenix.mvp.aop.MemoryCacheManager;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;

/**
 * Created by zhouphenix on 2016-12-25.
 * 根据MemoryCache注解自动添加缓存代理代码，通过aop切片的方式在编译期间织入源代码中
 * 功能：缓存某方法的返回值，下次执行该方法时，直接从缓存里获取
 */
@Aspect
public class MemoryCacheAspect {

    @Pointcut("execution(@com.phenix.annotation.aspect.MemoryCache * *(..))")
    public void methodAnnotated(){}

    @Around("methodAnnotated()")//在连接点进行方法替换
    public Object aroundJoinPoint(ProceedingJoinPoint joinPoint) throws Throwable {
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        String methodName = methodSignature.getName();
        MemoryCacheManager memoryCacheManager = MemoryCacheManager.getInstance();
        StringBuilder sb = new StringBuilder(methodName);
        for (Object o : joinPoint.getArgs()) {
            if (o instanceof String) sb.append(o.toString());
            else if( o instanceof Class) sb.append(((Class)o).getSimpleName());

        }
        String key = sb.toString();
        Object result = memoryCacheManager.get(key);//key规则 ： 方法名＋参数1+参数2+...
        if (result != null){
            Logger.t("MemoryCache").d("key：" + key + "--->" + result + " to get in cache");
            return result;//缓存已有，直接返回
        }
        result = joinPoint.proceed();//执行原方法
        memoryCacheManager.add(key, result);//存入缓存
        Logger.t("MemoryCache").d("key：" + key + "--->" + result + " to save to cache");
        return result;
    }

}
